package com.appspot.mercadobgbr.server;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Properties;

import javax.jdo.JDOObjectNotFoundException;
import javax.jdo.PersistenceManager;
import javax.jdo.Query;
import javax.jdo.Transaction;
import javax.mail.Message;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;

import com.appspot.mercadobgbr.client.JogosApi;
import com.appspot.mercadobgbr.shared.BoardGame;
import com.appspot.mercadobgbr.shared.Email;
import com.appspot.mercadobgbr.shared.Item;
import com.appspot.mercadobgbr.shared.Usuario;
import com.google.appengine.api.users.User;
import com.google.appengine.api.users.UserService;
import com.google.appengine.api.users.UserServiceFactory;
import com.google.gwt.user.server.rpc.RemoteServiceServlet;

/**
 * Implementation of Jogos API.
 */
@SuppressWarnings("serial")
public class JogosApiImpl extends RemoteServiceServlet implements JogosApi {
	public String getLoginUrl() {
		UserService userService = UserServiceFactory.getUserService();
		return userService.createLoginURL(getAppUrl());
	}

	public Item[] getItemList() {
		UserService userService = UserServiceFactory.getUserService();
		User user = userService.getCurrentUser();

		String email = null;
		if (user != null) {
			email = user.getEmail();
			String nickname = user.getNickname();
			PersistenceManager pm = PMF.get().getPersistenceManager();// pmf.getPersistenceManager();
			Usuario u = getPersistedUsuario(email, nickname, pm);
			u.setLogoutURL(userService.createLoginURL(getAppUrl()));

			List<Item> itens = new ArrayList<Item>();

			// Obter lista de BoardGames
			BoardGame[] boards = getBoardGamesNaoVendidos();

			List<Usuario> listaUsuarios = getPersistedUsuarios(pm);

			List<Email> emails = getEmailsEnviados(pm, u.getEmail());

			for (BoardGame board : boards) {
				for (Usuario usuario : listaUsuarios) {
					if (board.getEmail().equals(usuario.getEmail())) {
						board.setVendedor(usuario);
						break;
					}
				}
				for (Email e : emails) {
					if (e.getIdItem().equals(board.getId())) {
						board.setEnviado(true);
						break;
					}
				}
				itens.add(new Item(board));
			}

			itens.add(0, new Item(new BoardGame()));
			itens.get(0).setUsuario(u);

			// Marcar Adminitrador/Gerente
			if (u.getEmail().equals("saulo.achkar@gmail.com")) {
				u.setAdmin(true);
			}

			u.setGerente(true);

			pm.close();

			return itens.toArray(new Item[0]); // detachedJogos.toArray(new
												// Jogo[0]);
		} else {
			return null;
		}
	}

	@SuppressWarnings("unchecked")
	private List<Email> getEmailsEnviados(PersistenceManager pm, String email) {
		Query q = pm.newQuery(Email.class);
		q.setFilter("remetente == '" + email + "'");
		return (List<Email>) q.execute();
	}

	public Usuario[] getUsuarioList() {
		PersistenceManager pm = PMF.get().getPersistenceManager();// pmf.getPersistenceManager();
		List<Usuario> detachedUsuarioes = null;

		List<Usuario> persistedUsuarioes = getPersistedUsuarios(pm);

		detachedUsuarioes = (List<Usuario>) pm.detachCopyAll(persistedUsuarioes);
		pm.close();

		orderByNickname(detachedUsuarioes);

		return detachedUsuarioes.toArray(new Usuario[0]);
	}

	private void orderByNickname(List<Usuario> usuarioes) {
		Collections.sort(usuarioes, new Comparator<Usuario>() {
			public int compare(Usuario j1, Usuario j2) {
				return j1.getNickname().compareToIgnoreCase(j2.getNickname());
			}
		});
	}

	@SuppressWarnings("unchecked")
	public BoardGame[] getBoardGamesNaoVendidos() {
		PersistenceManager pm = PMF.get().getPersistenceManager();// pmf.getPersistenceManager();
		Query query = pm.newQuery(BoardGame.class);
		query.setFilter("vendido == false");
		query.setOrdering("name asc");
		return ((List<BoardGame>) pm.detachCopyAll((List<BoardGame>) query.execute()))
				.toArray(new BoardGame[0]);
	}

	private String getAppUrl() {
		String servletUrl = getThreadLocalRequest().getRequestURL().toString();
		String resourcePath = getThreadLocalRequest().getRequestURI();
		return servletUrl.replace(resourcePath, "");
	}

	@Override
	public String persistJogo(BoardGame boardGame) {
		PersistenceManager pm = PMF.get().getPersistenceManager();// pmf.getPersistenceManager();
		pm.makePersistent(boardGame);
		pm.close();
		return boardGame.getCodigoBGG();
	}

	private Usuario getPersistedUsuario(String email, String nickname, PersistenceManager pm) {
		Usuario j = null;
		try {
			j = (Usuario) pm.getObjectById(Usuario.class, email);
		} catch (JDOObjectNotFoundException e) {
			if (j == null) {
				j = new Usuario(email, nickname);
				pm.makePersistent(j);
				j.setPrimeiroAcesso(true);
			}
		}
		return j;

	}

	private BoardGame getPersistedBoardGame(String codigoBGG, PersistenceManager pm) {
		return (BoardGame) pm.getObjectById(BoardGame.class, codigoBGG);

	}

	public String persistUsuario(Usuario usuario) {
		String email = null;
		PersistenceManager pm = PMF.get().getPersistenceManager();// pmf.getPersistenceManager();
		Transaction tx = pm.currentTransaction();
		try {
			tx.begin();
			Usuario managedUsuario = (Usuario) pm.getObjectById(Usuario.class, usuario.getEmail());
			if (managedUsuario != null) {
				managedUsuario.setNickname(usuario.getNickname());
				managedUsuario.setLocal(usuario.getLocal());
				email = managedUsuario.getEmail();
			}
			tx.commit();
		} catch (Exception e) {
			if (tx.isActive()) {
				tx.rollback();
			}
		} finally {
			pm.close();
		}
		return email;
	}

	@SuppressWarnings("unchecked")
	private List<Usuario> getPersistedUsuarios(PersistenceManager pm) {
		return (List<Usuario>) pm.newQuery(Usuario.class).execute();
	}

	@Override
	public String persistJogo(Item item) {
		// TODO Auto-generated method stub
		return null;
	}

	public BoardGame[] getBoardGame(BoardGame boardGame) {
		BoardGame[] retorno = null;
		if (boardGame.getCodigoBGG() != null && !boardGame.getCodigoBGG().equals("")) {
			BGGXML.obterDadosBGG(boardGame);
			retorno = new BoardGame[] { boardGame.getName() == null ? null : boardGame };
		} else {
			ArrayList<BoardGame> listaJogos = BGGXML.obterListaJogos(boardGame.getName());
			if (listaJogos != null) {
				retorno = listaJogos.toArray(new BoardGame[0]);
			}
		}
		return retorno;
	}

	@Override
	public BoardGame[] getBoardGames() {
		return getBoardGamesNaoVendidos();
	}

	@Override
	public String enviarEmail(Email email) {
		String retorno = null;
		try {

			sendMail(
					email.getRemetente(),
					email.getNicknameComprador(),
					email.getDestinatario(),
					email.getNicknameVendedor(),
					email.getDestinatario(),
					"[Mercado BG-BR] Jogo: " + email.getNomeJogo() + " - Interessado: "
							+ email.getNicknameComprador(), email.getMensagem());
			PMF.get().getPersistenceManager().makePersistent(email);
			retorno = email.getIdItem();
		} catch (Exception e) {

		}
		return retorno;
	}

	private String sendMail(String from, String fromName, String to, String toName, String replyTo,
			String subject, String message) {
		String output = null;
		Properties props = new Properties();
		Session session = Session.getDefaultInstance(props, null);

		try {
			Message msg = new MimeMessage(session);
			msg.setFrom(new InternetAddress(from, fromName));
			msg.addRecipient(Message.RecipientType.TO, new InternetAddress(to, toName));
			msg.setSubject(subject);
			msg.setText(message);
			msg.setReplyTo(new InternetAddress[] { new InternetAddress(replyTo) });
			Transport.send(msg);

		} catch (Exception e) {
			output = e.toString();
		}
		return output;
	}

}
